import 'package:flutter/material.dart';
import 'dart:math';
import 'dart:async';
import 'package:flutter/services.dart';

void main() {
  runApp(const MaterialApp(
    home: RussiaBlocksDemo(),
  ));
}

class RussiaBlocksDemo extends StatefulWidget {
  const RussiaBlocksDemo({super.key});

  @override
  State<RussiaBlocksDemo> createState() => _RussiaBlocksDemoState();
}

class _RussiaBlocksDemoState extends State<RussiaBlocksDemo> {
  // 游戏板大小
  static const int rows = 20;
  static const int cols = 10;
  List<List<bool>> board = List.generate(rows, (_) => List.filled(cols, false));

  // 当前方块
  List<Offset> currentPiece = [];
  Offset currentPiecePosition = Offset.zero;

  // 自动下落定时器
  Timer? _timer;

  // 游戏是否结束
  bool isGameOver = false;

  // 焦点节点
  final FocusNode _focusNode = FocusNode();

  @override
  void initState() {
    super.initState();
    _newPiece();
    _startTimer();
    // 确保在initState中获取焦点
    WidgetsBinding.instance.addPostFrameCallback((_) {
      _focusNode.requestFocus();
    });
  }

  @override
  void dispose() {
    _timer?.cancel();
    _focusNode.dispose();
    super.dispose();
  }

  void _startTimer() {
    _timer = Timer.periodic(const Duration(milliseconds: 500), (timer) {
      if (!isGameOver) {
        _movePiece(const Offset(0, 1));
      }
    });
  }

  void _newPiece() {
    // 随机选择一个方块
    currentPiece = List.from(_pieces[Random().nextInt(_pieces.length)]);
    currentPiecePosition = const Offset(cols / 2 - 1, 0);
    if (_checkCollision()) {
      setState(() {
        isGameOver = true;
      });
      _timer?.cancel();
      return;
    }
  }

  bool _checkCollision() {
    for (var offset in currentPiece) {
      int x = (currentPiecePosition.dx + offset.dx).toInt();
      int y = (currentPiecePosition.dy + offset.dy).toInt();
      // 添加边界检查
      if (x < 0 || x >= cols || y < 0 || y >= rows || board[y][x]) {
        return true;
      }
    }
    return false;
  }

  void _movePiece(Offset delta) {
    if (isGameOver) return;
    Offset newPosition = currentPiecePosition + delta;
    for (var offset in currentPiece) {
      int x = (newPosition.dx + offset.dx).toInt();
      int y = (newPosition.dy + offset.dy).toInt();
      // 添加边界检查，防止方块超出下方边界
      if (x < 0 || x >= cols || y < 0 || y >= rows || board[y][x]) {
        if (delta.dy > 0) {
          _lockPiece();
        }
        return;
      }
    }
    setState(() {
      currentPiecePosition = newPosition;
    });
  }

  void _lockPiece() {
    // 将当前方块锁定到游戏板上
    for (var offset in currentPiece) {
      int x = (currentPiecePosition.dx + offset.dx).toInt();
      int y = (currentPiecePosition.dy + offset.dy).toInt();
      if (y >= 0 && y < rows && x >= 0 && x < cols) {
        board[y][x] = true;
      }
    }
    _newPiece();
  }

  void _rotatePiece() {
    if (isGameOver) return;
    List<Offset> rotatedPiece = currentPiece.map((offset) => Offset(-offset.dy, offset.dx)).toList();
    for (var offset in rotatedPiece) {
      int x = (currentPiecePosition.dx + offset.dx).toInt();
      int y = (currentPiecePosition.dy + offset.dy).toInt();
      // 添加边界检查
      if (x < 0 || x >= cols || y < 0 || y >= rows || board[y][x]) {
        return;
      }
    }
    setState(() {
      currentPiece = rotatedPiece;
    });
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text('俄罗斯方块'),
        elevation: 0,
      ),
      body: RawKeyboardListener(
        focusNode: _focusNode,
        onKey: (RawKeyEvent event) {
          if (event is RawKeyDownEvent) {
            if (event.logicalKey == LogicalKeyboardKey.arrowLeft) {
              _movePiece(const Offset(-1, 0));
            } else if (event.logicalKey == LogicalKeyboardKey.arrowRight) {
              _movePiece(const Offset(1, 0));
            } else if (event.logicalKey == LogicalKeyboardKey.arrowDown) {
              _movePiece(const Offset(0, 1));
            } else if (event.logicalKey == LogicalKeyboardKey.arrowUp) {
              _rotatePiece();
            }
          }
        },
        child: GestureDetector(
          onTap: _rotatePiece,
          onLongPress: () {
            _timer?.cancel();
            _timer = Timer.periodic(const Duration(milliseconds: 100), (timer) {
              _movePiece(const Offset(0, 1));
            });
          },
          onLongPressEnd: (_) {
            _timer?.cancel();
            _startTimer();
          },
          // ignore: sized_box_for_whitespace
          child: Container(
            height: MediaQuery.of(context).size.height - kToolbarHeight - kBottomNavigationBarHeight, // 调整高度
            child: GridView.builder(
              physics: const NeverScrollableScrollPhysics(),
              itemCount: rows * cols,
              gridDelegate: const SliverGridDelegateWithFixedCrossAxisCount(crossAxisCount: cols),
              itemBuilder: (context, index) {
                int x = index % cols;
                int y = index ~/ cols;
                bool isCurrentPiece = currentPiece.any((offset) => (currentPiecePosition.dx + offset.dx).toInt() == x && (currentPiecePosition.dy + offset.dy).toInt() == y);
                return Container(
                  decoration: BoxDecoration(
                    border: Border.all(color: Colors.grey),
                    color: isCurrentPiece ? Colors.blue : board[y][x] ? Colors.blue : Colors.transparent,
                  ),
                );
              },
            ),
          ),
        ),
      ),
    );
  }

  static const List<List<Offset>> _pieces = [
    [Offset(0, 0), Offset(1, 0), Offset(2, 0), Offset(3, 0)], // I
    [Offset(0, 0), Offset(1, 0), Offset(0, 1), Offset(1, 1)], // O
    [Offset(0, 0), Offset(1, 0), Offset(2, 0), Offset(1, 1)], // T
    [Offset(0, 0), Offset(1, 0), Offset(2, 0), Offset(2, 1)], // L
    [Offset(0, 1), Offset(1, 1), Offset(2, 1), Offset(2, 0)], // J
    [Offset(0, 0), Offset(1, 0), Offset(1, 1), Offset(2, 1)], // S
    [Offset(0, 1), Offset(1, 1), Offset(1, 0), Offset(2, 0)], // Z
  ];
}
